package cn.ym.user.service.impl;

import cn.ym.basic.exception.BusinessException;
import cn.ym.basic.utils.AjaxResult;
import cn.ym.basic.utils.Md5Utils;
import cn.ym.basic.utils.StrUtils;
import cn.ym.user.domain.Logininfo;
import cn.ym.user.domain.User;
import cn.ym.user.mapper.LogininfoMapper;
import cn.ym.user.mapper.UserMapper;
import cn.ym.user.service.IUserService;
import cn.ym.basic.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Map;

/**
 * 业务实现类：用户
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;
    /**
     * 邮箱注册
     * @param map
     */
    @Transactional
    @Override
    public void emailRegister(Map<String, String> map) throws MessagingException {
        //1.空值校验+密码校验+判断邮箱是否注册
        String email = map.get("email");
        String password = map.get("password");
        String passwordRepeat = map.get("passwordRepeat");
        //1.1：校验 - 空值校验
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordRepeat)){
            throw new BusinessException("邮箱注册信息不能为空！！！");
        }
        //1.2：校验 - 密码是否一致
        if( !password.equals(passwordRepeat)){
            throw new BusinessException("两次输入的密码是否一致");
        }
        //1.3.判断该邮箱是否已经被注册过 - 怎么判断注册？邮箱名
        User dbEmail = userMapper.findByEmail(email);
        if(dbEmail != null){
            throw new BusinessException("邮箱已经注册过，请直接登陆！忘记密码请找回密码");
        }

        //2.保存user信息和logininfo信息
        User user = getUserEmail(email, password);

        //3.保存logininfo信息表
        Logininfo logininfo=new Logininfo();
        BeanUtils.copyProperties(user,logininfo);//属性同名原则可以复制
        logininfo.setType(1);//1=用户
        logininfo.setDisable(false);//禁用 --激活后启用
        //4.先添加t_logininfo
        logininfoMapper.add(logininfo);//添加之后会生成自增长id
        //5.再添加t_user
        user.setLogininfoId(logininfo.getId());
        //调用mapper接口添加user对象
        userMapper.add(user);

        /**发送邮件：告诉用户激活邮件使用*/

        //创建复杂邮件对象
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        //发送复杂邮件的工具类
        //true - 能够添加附件
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
        //发送人
        helper.setFrom("210513347@qq.com");
        helper.setSubject("邮箱注册激活邮件");
        //true - 能够再内容中编写html标签 - 会解析
        helper.setText("<h1>你已经注册邮箱!<a href='http://127.0.0.1:8080/user/active/"
                        +user.getLogininfoId()+"'>点击该链接激活</a>",
                true);
        //收件人
        helper.setTo(user.getEmail());
        javaMailSender.send(mimeMessage);

    }

    private User getUserEmail(String email, String password) {
        User user = new User();
        user.setUsername(email);
        user.setEmail(email);
        //获取一个新的盐值
        String salt = StrUtils.getComplexRandomString(32);
        user.setSalt(salt);
        //加密密码
        String md5 = Md5Utils.encrypByMd5(password + salt);//对设置的密码进行加密加盐
        user.setPassword(md5);
        user.setState(0);//先设置禁用
        return user;
    }


    /**
     * 邮箱注册---发送邮件---激活
     * @param id
     */
    @Transactional
    @Override
    public void active(Long id) {
        //修改longininfo的状态
        Logininfo logininfo = logininfoMapper.findOne(id);
        logininfo.setDisable(true);//启用
        logininfoMapper.update(logininfo);
        //2.修改用户的状态--通过longininfoid修改状态
        User user = userMapper.findByLogininfoId(logininfo.getId());
        user.setState(1);
        userMapper.update(user);
    }





    /**
     * 手机号注册
     * @param map
     */
    @Transactional
    @Override
    public AjaxResult phoneRegister(Map<String, String> map) {
        String phone = map.get("phone");//号码
        String phoneCode = map.get("phoneCode");//验证码
        String password = map.get("password");//密码
        String passwordRepeat = map.get("passwordRepeat");//二次密码


        //一：校验 - 空值校验
        if(StringUtils.isBlank(phone) || StringUtils.isBlank(phoneCode)
                || StringUtils.isBlank(password)  || StringUtils.isBlank(passwordRepeat)){
            throw new BusinessException("信息不能为空");
        }
        //二：校验 - 密码是否一致
        if(!password.equals(passwordRepeat)){
            throw new BusinessException("两次密码不一致");
        }
        //三：校验 - 手机验证码是否过期，是否正确 [9555:4545455454545]
        Object obj = redisTemplate.opsForValue().get("register:" + phone);
        if (obj==null){
            throw new BusinessException("手机验证码过期了");
        }
        //从redis里面分割出来 的 手机验证码  和前端传过来的进行对比
        if (!obj.toString().split(":")[0].equals(phoneCode)){
            throw new BusinessException("手机验证码错误");
        }
        //四：添加到数据库---要处理盐值和密码
        //4.2先保存t_logininfo，会生成一个自增长id
        Logininfo logininfo = saveLogininfo(phone);

        //4.2再保存t_user表添加到数据库
        User user = new User();
        BeanUtils.copyProperties(logininfo,user);//属性同名原则可以复制
        user.setState(1);//启用
        user.setLogininfoId(logininfo.getId());
        userMapper.add(user);
        return new AjaxResult();
    }

    @Override
    public User findBylogininfoId(Long logininfoId) {

        return userMapper.findByLogininfoId(logininfoId);
    }


    private Logininfo saveLogininfo(String phone) {
        Logininfo logininfo = new Logininfo();
        logininfo.setUsername(phone);
        logininfo.setPhone(phone);
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(logininfo.getPassword() + salt);
        logininfo.setSalt(salt);//设置盐值
        logininfo.setPassword(md5Pwd);//设置加盐加密后的密码
        logininfo.setType(1);//用户
        logininfo.setDisable(true);//启用
        logininfoMapper.add(logininfo);//添加之后会生成自增长id
        return logininfo;
    }



    @Transactional
    @Override
    public void add(User user) {
        //1.处理盐值和密码
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        //2.创建Logininfo对象
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);//属性同名原则可以复制
        logininfo.setType(1);//1=用户
        logininfo.setDisable(true);//启用
        //3.将Logininfo对象添加到数据库，并生成自增id
        logininfoMapper.add(logininfo);
        //4.将logininfo_id设置到user对象中
        user.setLogininfoId(logininfo.getId());
        //5.添加到数据库
        super.add(user);
    }
    @Transactional
    @Override
    public void update(User user) {
        //1.处理盐值和密码
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);

        //2.查询到原来的user对象
        User oldUser = userMapper.findOne(user.getId());
        Logininfo oldlogininfo = logininfoMapper.findOne(oldUser.getLogininfoId());

        //3.更新数据t_logininfo
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);//属性同名原则可以复制
        logininfo.setId(oldlogininfo.getId());
        logininfo.setType(oldlogininfo.getType());
        logininfo.setDisable(oldlogininfo.getDisable());
        //更新logininfo
        logininfoMapper.update(oldlogininfo);
        //更新user
        super.update(user);
    }
    @Transactional
    @Override
    public void delete(Long id) {
        //1.查询user对象
        User user = userMapper.findOne(id);
        //2.删除logininfo信息
        logininfoMapper.delete(user.getLogininfoId());
        //3.删除user信息
        super.delete(id);
    }
    @Transactional
    @Override
    public void patchDel(Long[] ids) {
        for (Long id : ids) {
            delete(id);
        }
    }

}
